using System;
using System.Collections.Generic;
using UnityEngine;

namespace MLTimeline.Editor
{
    public class TickHandler
    {
        private readonly int[] _tickLevels;
        private readonly float[] _tickStrengths;
        private readonly List<int> _tickListCache = new List<int>(1000);

        // 使用 double 来避免精度问题
        private double _minFrame;
        private double _maxFrame;
        private double _pixelWidth;

        public int SmallestTickIndex { get; private set; }
        public int BiggestTickIndex { get; private set; }

        public TickHandler(int[] tickLevels)
        {
            _tickLevels = tickLevels;
            _tickStrengths = new float[tickLevels.Length];
        }

        public void SetRanges(double minFrame, double maxFrame, double pixelWidth)
        {
            _minFrame = minFrame;
            _maxFrame = maxFrame;
            _pixelWidth = pixelWidth;
        }

        public void CalculateTickStrengths(float minPixelSpacing, float maxPixelSpacing, bool useSqrt)
        {
            SmallestTickIndex = 0;
            BiggestTickIndex = -1; // 默认为-1，表示没有可见的

            double frameRange = _maxFrame - _minFrame;
            if (frameRange <= 0) return;

            for (int i = 0; i < _tickLevels.Length; i++)
            {
                double spacing = _tickLevels[i] * _pixelWidth / frameRange;

                if (spacing >= minPixelSpacing)
                {
                    BiggestTickIndex = i; // 持续更新，找到最粗的可见级别
                    _tickStrengths[i] = (float)((spacing - minPixelSpacing) / (maxPixelSpacing - minPixelSpacing));
                }
                else
                {
                    _tickStrengths[i] = 0;
                }
            }

            // 找到第一个可见的tick作为SmallestTick
            for (int i = 0; i < _tickLevels.Length; i++)
            {
                double spacing = _tickLevels[i] * _pixelWidth / frameRange;
                if (spacing >= minPixelSpacing)
                {
                    SmallestTickIndex = i;
                    break;
                }
            }

            if (BiggestTickIndex == -1) return;

            for (int i = SmallestTickIndex; i <= BiggestTickIndex; i++)
            {
                _tickStrengths[i] = Mathf.Clamp01(_tickStrengths[i]);
                if (useSqrt)
                {
                    _tickStrengths[i] = Mathf.Sqrt(_tickStrengths[i]);
                }
            }
        }

        public List<int> GetTicks(int levelIndex, bool excludeHigherLevels)
        {
            _tickListCache.Clear();
            long tickStep = _tickLevels[levelIndex];

            // 检查计算范围是否过大，防止编辑器卡死
            if ((_maxFrame - _minFrame) / tickStep > 10000)
            {
                return _tickListCache;
            }

            long startTick = (long)Math.Floor(_minFrame / tickStep);
            long endTick = (long)Math.Ceiling(_maxFrame / tickStep);

            long? higherLevelStep = null;
            if (excludeHigherLevels && levelIndex < _tickLevels.Length - 1)
            {
                higherLevelStep = _tickLevels[levelIndex + 1];
            }

            for (long i = startTick; i <= endTick; i++)
            {
                long frame = i * tickStep;
                if (frame < 0) continue; // 确保帧号为正

                if (higherLevelStep.HasValue && frame % higherLevelStep.Value == 0)
                {
                    continue;
                }

                // 确保不会添加超出int范围的帧
                if (frame <= int.MaxValue)
                {
                    _tickListCache.Add((int)frame);
                }
            }

            return _tickListCache;
        }

        public float GetStrength(int levelIndex)
        {
            if (levelIndex < 0 || levelIndex >= _tickStrengths.Length) return 0;
            return _tickStrengths[levelIndex];
        }

        public int GetLevelForLabels(float minPixelSpacing)
        {
            double frameRange = _maxFrame - _minFrame;
            if (frameRange <= 0) return -1;

            for (int i = 0; i < _tickLevels.Length; i++)
            {
                double spacing = _tickLevels[i] * _pixelWidth / frameRange;
                if (spacing >= minPixelSpacing)
                {
                    return i;
                }
            }
            return -1;
        }
    }
}